{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Impact of `p_error` on neural networks\n",
    "\n",
    "This tutorial aims to show the effect of the hyperparameter `p_error` on neural networks during Fully Homomorphic Encryption (FHE) execution.\n",
    "\n",
    "At Zama, non-linear operations are implemented using table lookup (TLU), which are implemented\n",
    "through the Programmable Bootstrapping technology (PBS). The hyperparameter `p_error` represents the probability of a single PBS operation being incorrect. For further information on `p_error`, please refer to this [link](https://docs.zama.ai/concrete-ml/explanations/advanced_features).\n",
    "\n",
    "<!-- Separate FMNIST from CIFAR directory -->\n",
    "<!-- #FIXME: https://github.com/zama-ai/concrete-ml-internal/issues/3552 -->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### import required packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random\n",
    "from itertools import chain\n",
    "from time import time\n",
    "\n",
    "import concrete.compiler\n",
    "import matplotlib.pylab as plt\n",
    "import numpy\n",
    "import torch\n",
    "from cifar_utils import get_dataloader, mapping_keys, plot_dataset, torch_inference, train\n",
    "from sklearn.metrics import top_k_accuracy_score\n",
    "\n",
    "from concrete.ml.pytest.torch_models import QNNFashionMNIST\n",
    "from concrete.ml.pytest.utils import data_calibration_processing\n",
    "from concrete.ml.search_parameters import BinarySearch\n",
    "from concrete.ml.torch.compile import compile_brevitas_qat_model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setting "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Device Type: cuda:0\n"
     ]
    }
   ],
   "source": [
    "param = {\n",
    "    \"batch_size\": 128,\n",
    "    \"dataset_name\": \"FashionMNIST\",\n",
    "    \"quant_state_dict\": \"./checkpoints/FashionMNIST/quant/FashionMNIST_quant_state_dict.pt\",\n",
    "    \"fp32_state_dict\": \"./checkpoints/FashionMNIST/fp32/FashionMNIST_fp32_state_dict.pt\",\n",
    "    \"seed\": 42,\n",
    "}\n",
    "\n",
    "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "\n",
    "print(f\"Device Type: {device}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Concrete ML also supports a CUDA-enabled backend. To set it up, follow the instructions in the official [guide](../../../docs/guides/using_gpu.md) for installing the GPU-enabled Concrete compiler."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "compilation_device = \"cuda\" if concrete.compiler.check_gpu_available() else \"cpu\"\n",
    "\n",
    "print(f\"Is GPU enabled: {concrete.compiler.check_gpu_enabled()}\")\n",
    "print(f\"Is GPU available: {concrete.compiler.check_gpu_available()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Display the FashionMnist data\n",
    "\n",
    "For this experiment, we have chosen the FashionMnist data-set."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1200x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_loader, test_loader = get_dataloader(param=param)\n",
    "\n",
    "plot_dataset(test_loader, param)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 70.4327%\n"
     ]
    }
   ],
   "source": [
    "# Choose a lower quantization bit to get reasonable compilation and inference time\n",
    "quant_model = QNNFashionMNIST(n_bits=2)\n",
    "\n",
    "training = False\n",
    "\n",
    "if training:\n",
    "    # To train the Fashion MNIST model, first, we assign float32 weights, and we then fine-tune\n",
    "    # the weights using Quantization Aware Training\n",
    "\n",
    "    param = {\n",
    "        **param,\n",
    "        # Add some parameters required for the training\n",
    "        **{\n",
    "            \"accuracy_test\": [],\n",
    "            \"accuracy_train\": [],\n",
    "            \"loss_test_history\": [],\n",
    "            \"loss_train_history\": [],\n",
    "            \"dir\": \"./checkpoints/FashionMNIST\",\n",
    "            \"criterion\": torch.nn.CrossEntropyLoss(),\n",
    "            \"training\": \"quant\",\n",
    "            \"lr\": 0.001,\n",
    "            \"epochs\": 30,\n",
    "            \"gamma\": 0.01,\n",
    "            \"milestones\": [100],\n",
    "        },\n",
    "    }\n",
    "\n",
    "    checkpoint = torch.load(param[\"fp32_state_dict\"], map_location=device)\n",
    "    quant_model = mapping_keys(checkpoint, quant_model, device)\n",
    "    print(\n",
    "        \"Accuracy before fine-tuning:\"\n",
    "        f\"{torch_inference(quant_model, test_loader, param, device): .4f}\"\n",
    "    )\n",
    "    quant_model = train(quant_model, train_loader, test_loader, param, device=device)\n",
    "else:\n",
    "    # Upload directly pre-tained weights\n",
    "    checkpoint = torch.load(param[\"quant_state_dict\"], map_location=\"cpu\")\n",
    "    quant_model.load_state_dict(checkpoint)\n",
    "\n",
    "print(f\"Accuracy: {torch_inference(quant_model, test_loader, param, device):.4%}\")\n",
    "\n",
    "# GPU mode is still not supported yet\n",
    "quant_model = quant_model.cpu()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Data for calibration and compilation\n",
    "X_calib, y_calib = data_calibration_processing(data=train_loader, n_sample=60)\n",
    "\n",
    "# Testing set for the FHE simulation mode\n",
    "X_test, y_test = data_calibration_processing(data=train_loader, n_sample=100)\n",
    "\n",
    "# For the FHE execution, 1 sample is used to measure the inference time\n",
    "X_fhe_test, y_fhe_test = data_calibration_processing(data=test_loader, n_sample=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iter:  0 - p_error=0.000067548, accuracy=70.00% inference_time=7.1393, compilation_time=0.0347,  max_bitwidth=7\n",
      "Iter:  1 - p_error=0.000012251, accuracy=70.00% inference_time=7.2961, compilation_time=0.0345,  max_bitwidth=7\n",
      "Iter:  2 - p_error=0.000034753, accuracy=70.00% inference_time=7.1990, compilation_time=0.0347,  max_bitwidth=7\n",
      "Iter:  3 - p_error=0.000030089, accuracy=70.00% inference_time=7.2431, compilation_time=0.0358,  max_bitwidth=7\n",
      "Iter:  4 - p_error=0.000762824, accuracy=72.00% inference_time=7.0666, compilation_time=0.0350,  max_bitwidth=7\n",
      "Iter:  5 - p_error=0.000709030, accuracy=72.00% inference_time=6.9790, compilation_time=0.0342,  max_bitwidth=7\n",
      "Iter:  6 - p_error=0.000902962, accuracy=69.00% inference_time=7.1151, compilation_time=0.0346,  max_bitwidth=7\n",
      "Iter:  7 - p_error=0.000178245, accuracy=70.00% inference_time=7.1713, compilation_time=0.0345,  max_bitwidth=7\n",
      "Iter:  8 - p_error=0.004797296, accuracy=71.00% inference_time=6.8009, compilation_time=0.0348,  max_bitwidth=7\n",
      "Iter:  9 - p_error=0.001268175, accuracy=69.00% inference_time=7.0433, compilation_time=0.0351,  max_bitwidth=7\n",
      "Iter: 10 - p_error=0.002967742, accuracy=73.00% inference_time=6.6892, compilation_time=0.0353,  max_bitwidth=7\n",
      "Iter: 11 - p_error=0.005548198, accuracy=75.00% inference_time=6.7126, compilation_time=0.0351,  max_bitwidth=7\n",
      "Iter: 12 - p_error=0.033617013, accuracy=53.00% inference_time=2.9932, compilation_time=0.0358,  max_bitwidth=7\n",
      "Iter: 13 - p_error=0.186965509, accuracy=15.00% inference_time=1.5601, compilation_time=0.0340,  max_bitwidth=7\n",
      "Iter: 14 - p_error=0.588397150, accuracy=14.00% inference_time=0.7278, compilation_time=0.0338,  max_bitwidth=7\n",
      "Iter: 15 - p_error=0.494997918, accuracy=10.00% inference_time=0.9395, compilation_time=0.0370,  max_bitwidth=7\n"
     ]
    }
   ],
   "source": [
    "inference_time, compilation_time, simulated_accuracy = [], [], []\n",
    "\n",
    "# `p_error` is bounded between 0 and 0.9\n",
    "# Generate random p_error values with different ranges of scales, such as:\n",
    "# 0.00001, 0.0001, 0.001, 0.01, and 0.1. In order to measure the inference time\n",
    "random_p_errors = list(\n",
    "    chain(\n",
    "        *[\n",
    "            [random.uniform(a, b) for _ in range(4)]\n",
    "            for a, b in [(0.00001, 0.0001), (0.0001, 0.001), (0.001, 0.01), (0.01, 0.9)]\n",
    "        ]\n",
    "    )\n",
    ")\n",
    "\n",
    "for i, p_error in enumerate(random_p_errors):\n",
    "\n",
    "    start_time = time()\n",
    "    qmodel = compile_brevitas_qat_model(\n",
    "        torch_model=quant_model,\n",
    "        torch_inputset=X_calib,\n",
    "        p_error=p_error,\n",
    "        device=compilation_device,\n",
    "    )\n",
    "    compilation_time.append((time() - start_time) / 60.0)\n",
    "\n",
    "    # Key Generation.\n",
    "    qmodel.fhe_circuit.keygen(force=False)\n",
    "\n",
    "    # Evaluating the model compiled with a given `p_error` in FHE simulation mode\n",
    "    y_pred_simulated = qmodel.forward(X_test, fhe=\"simulate\")\n",
    "    simulated_accuracy.append((y_pred_simulated.argmax(axis=1) == y_test).mean())\n",
    "\n",
    "    # Measuring the inference time for a model compiled with a given `p_error` in real FHE mode\n",
    "    # on 1 single example\n",
    "    start_time = time()\n",
    "    _ = qmodel.forward(X_fhe_test, fhe=\"execute\")\n",
    "    inference_time.append((time() - start_time) / 60.0)\n",
    "\n",
    "    print(\n",
    "        f\"Iter: {i:2} - p_error={p_error:1.9f}, accuracy={simulated_accuracy[-1]:.2%} \"\n",
    "        f\"inference_time={inference_time[-1]:1.4f}, compilation_time={compilation_time[-1]:1.4f}, \",\n",
    "        f\"max_bitwidth={qmodel.fhe_circuit.graph.maximum_integer_bit_width()}\",\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualize the impact of `p_error`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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7aEGAMSnsSBGRBWbTCaDv78/KleuDK1WK3U4ZYpWq8XevXvRunVr3s5nhSfl0d7enjPDyKwJXcIAAD/8fdVou1z2sBim309ERETlGwtiRRTi8XCGWGpWKrLysuDs4CxxRERE0lIoFCw8FJFCoUB+fj4cHR1ZELMC80jFNaFLGMa0q44/d2zDgGZVEeTlgtdbqjkzjIiIqAJhQayIPJ084a50R3puOq6lX0OYD/+KSERERFTW6ItfH3cJZUGViIioAuKfwYqB64gREREREREREZVdLIgVA9cRIyIiIiIiIiIqu1gQKwb9OmKcIUZEREREREREVPawIFYM+oJYQnqCtIEQEREREREREVGRsSBWDFxDjIiIiIiIiIio7GJBrBi4hhgRERERERERUdnFglgx6AtiaTlpSMtJkzQWIiIiIiIiIiIqGhbEisHFwQU+Kh8AQEJagrTBEBERERERERFRkbAgVkyG2ya5jhgRERERERERUZnCglgxGRbW5zpiRERERERERERlCgtixRTi8bAgxlsmiYiIiIiIiIjKFhbEiklfEOMMMSIiIiIiIiKisoUFsWLiGmJERERERERERGUTC2LF9OgaYoIgSBwNERERERERERFZigWxYgp2D4YMMmRrs3En+47U4RARERERERERkYVYECsmpZ0SAa4BALiOGBERERERERFRWcKCmBW4jhgRERERERERUdnDgpgVHl1HjIiIiIiIiIiIygYWxKwQ4vGwIJaQliBtIEREREREREREZDHJC2I3b97Ea6+9hkqVKsHJyQn169fH0aNHpQ7LIoZbJjlDjIiIiIiIiIiozLCT8uT379/Hc889h3bt2uGPP/6Aj48PLl26BE9PTynDsph+hhjXECMiIiIiIiIiKjskLYh9+eWXCAoKwrJlywzbQkJCJIyoaPRriF1LvwadoINcJvmEOyIiIiIiIiIiegpJC2JbtmxBp06d8Morr2DPnj0IDAzEqFGjMGLECLPtc3NzkZuba3it0WgAAFqtFlqtVvT49H0W1revky8UMgXyCvKQeD8Rga6BosdQHjwtj/R0zKE4mEdxMI/WYw7FYU0emXsiIiKiik3SgtjVq1exYMECREVF4aOPPsKRI0cwZswYODg4YPDgwSbtY2JiEB0dbbJ9x44dUKlUNoszNja20H2V7CshNS8Vq/9YjTCXMJvFUB48KY9kGeZQHMyjOJhH6zGH4ihOHrOzs20QCRERERGVFZIWxHQ6HZo0aYKpU6cCABo3bowzZ85g4cKFZgtiEyZMQFRUlOG1RqNBUFAQOnbsCDc3N9Hj02q1iI2NRUREBOzt7c22CbsfhtRrqfAL9UOX+l1Ej6E8sCSP9GTMoTiYR3Ewj9ZjDsVhTR71s8yJiIiIqGKStCDm7++PsDDjWVWhoaHYsGGD2fZKpRJKpdJku729vU1/oXhS/9U8qyHuWhxuZNzgLzVPYevPqSJgDsXBPIqDebQecyiO4uSReSciIiKq2CRdBf65557DhQsXjLZdvHgRwcHBEkVUdPqF9ePT+KRJIiIiIiIiIqKyQNKC2HvvvYeDBw9i6tSpuHz5MlatWoXvvvsOo0ePljKsIlF7qAGwIEZEREREREREVFZIWhBr2rQpNm3ahNWrV6NevXqYMmUKZs+ejYEDB0oZVpGEePz/DLH7LIgREREREREREZUFkq4hBgAvvfQSXnrpJanDKDb9LZM3NDeQr8uHnVzylBIRERERERER0RNIOkOsPPBz8YNSoUSBUIDr6delDoeIiIiIiIiIiJ6CBTEryWVyBHs8fAgA1xEjIiIiIiIiIir9WBATAdcRIyIiIiIiIiIqO1gQE4G+IJaQliBtIERERERERERE9FQsiIlA7aEGwFsmiYiIiIiIiIjKAhbERKB/0iQLYkREREREREREpR8LYiLgLZNERERERERERGUHC2Ii0M8Qu5VxCzn5ORJHQ0RERCS+efPmQa1Ww9HREc2bN8fhw4ef2D4tLQ2jR4+Gv78/lEolatWqha1bt5ZQtERERERPxoKYCCo5VYKzvTMA4FraNYmjISIiIhLX2rVrERUVhUmTJuH48eNo2LAhOnXqhNTUVLPt8/LyEBERgYSEBKxfvx4XLlzA4sWLERgYWMKRExEREZnHgpgIZDIZ1xEjIiKicmvmzJkYMWIEhg4dirCwMCxcuBAqlQpLly41237p0qW4d+8eNm/ejOeeew5qtRpt2rRBw4YNSzhyIiIiIvPspA6gvAjxCMGZ1DNcR4yIiIjKlby8PBw7dgwTJkwwbJPL5ejQoQMOHDhg9pgtW7agZcuWGD16NH755Rf4+Pjg1Vdfxfjx46FQKMwek5ubi9zcXMNrjUYDANBqtdBqtSK+Ixj6ffT/qXiYR3Ewj9ZjDsXBPFqPORSHNXm09BgWxESiX1g//j5niBEREVH5cefOHRQUFMDX19dou6+vL86fP2/2mKtXr2LXrl0YOHAgtm7disuXL2PUqFHQarWYNGmS2WNiYmIQHR1tsn3Hjh1QqVTWv5FCxMbG2qzvioR5FAfzaD3mUBzMo/WYQ3EUJ4/Z2dkWtWNBTCRqDzUA3jJJREREpNPpULlyZXz33XdQKBQIDw/HzZs3MX369EILYhMmTEBUVJThtUajQVBQEDp27Ag3NzfRY9RqtYiNjUVERATs7e1F77+iYB7FwTxajzkUB/NoPeZQHNbkUT/L/GlYEBMJ1xAjIiKi8sjb2xsKhQIpKSlG21NSUuDn52f2GH9/f9jb2xvdHhkaGork5GTk5eXBwcHB5BilUgmlUmmy3d7e3qa/UNi6/4qCeRQH82g95lAczKP1mENxFCePlrbnovoi0d8yyTXEiIiIqDxxcHBAeHg4du7cadim0+mwc+dOtGzZ0uwxzz33HC5fvgydTmfYdvHiRfj7+5sthhERERGVNBbERKK/ZfJO9h1k5mVKGwwRERGRiKKiorB48WKsWLEC586dw8iRI5GVlYWhQ4cCAAYNGmS06P7IkSNx7949vPvuu7h48SJ+//13TJ06FaNHj5bqLRAREREZ4S2TInF3dIenoyfu59xH/P141PetL3VIRERERKLo168fbt++jYkTJyI5ORmNGjXCtm3bDAvtJyYmQi7/7++sQUFB2L59O9577z00aNAAgYGBePfddzF+/Hip3gIRERGRERbERBTiGYL7SfeRkJbAghgRERGVK5GRkYiMjDS7Ly4uzmRby5YtcfDgQRtHRURERFQ8vGVSRPp1xLiwPhERERERERFR6cWCmIj064jF32dBjIiIiIiIiIiotGJBTEScIUZEREREREREVPqxICaiEM+HBbGEtARpAyEiIiIiIiIiokKxICaiR2eICYIgcTRERERERERERGQOC2IiCvYIBgBocjW4n3Nf4miIiIiIiIiIiMgcFsREpLJXwdfZFwAX1iciIiIiIiIiKq1YEBMZ1xEjIiIiIiIiIirdWBATGZ80SURERERERERUurEgJjK1hxoAb5kkIiIiIiIiIiqtWBATGWeIERERERERERGVbiyIiYxriBERERERERERlW4siIlMf8tkQloCBEGQNhgiIiIiIiIiIjLBgpjI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",
      "text/plain": [
       "<Figure size 1500x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig, axes = plt.subplots(1, 2, figsize=(15, 5))\n",
    "\n",
    "axes[0].plot(random_p_errors, inference_time, label=\"Inference time\", color=\"green\", marker=\"o\")\n",
    "axes[0].plot(\n",
    "    random_p_errors, compilation_time, label=\"Compilation time\", color=\"orange\", marker=\"o\"\n",
    ")\n",
    "axes[1].scatter(random_p_errors, simulated_accuracy, label=\"Accuracy\", marker=\"o\")\n",
    "\n",
    "axes[0].set_title(\"Impact of p_error on inference time\")\n",
    "axes[1].set_title(\"Impact of p_error on model's performance\")\n",
    "\n",
    "axes[0].set_ylabel(\"Timing (s)\")\n",
    "axes[1].set_ylabel(\"Accuracy\")\n",
    "\n",
    "axes[0].set_xlabel(\"p_error\")\n",
    "axes[1].set_xlabel(\"p_error\")\n",
    "\n",
    "axes[0].grid(True)\n",
    "axes[1].grid(True)\n",
    "\n",
    "axes[0].legend()\n",
    "axes[1].legend()\n",
    "\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As the value of `p_error` increases, the inference time in FHE decreases, but the model's performance is affected. For custom ML models, it is recommended to search in simulated FHE mode to find a `p_error` that offers an interesting compromise between accuracy and execution time. In Concrete ML, we have proposed a binary search algorthm showed in [Searching for the best error probability](https://docs.zama.ai/concrete-ml/explanations/advanced_features)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Binary search algorithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "With p_error = 0.00121, the inference time per example becomes 7.04s and accuracy = 73.00%\n"
     ]
    }
   ],
   "source": [
    "search = BinarySearch(estimator=quant_model, predict=\"predict\", metric=top_k_accuracy_score, k=1)\n",
    "\n",
    "largest_p_error = search.run(x=X_calib, ground_truth=y_calib, max_iter=30, verbose=False)\n",
    "\n",
    "# Compile the model with the optimal `p_error`\n",
    "qmodel = compile_brevitas_qat_model(\n",
    "    torch_model=quant_model,\n",
    "    torch_inputset=X_calib,\n",
    "    p_error=largest_p_error,\n",
    "    device=compilation_device,\n",
    ")\n",
    "\n",
    "# Key Generation\n",
    "qmodel.fhe_circuit.keygen(force=False)\n",
    "\n",
    "start_time = time()\n",
    "_ = qmodel.forward(X_fhe_test, fhe=\"execute\")\n",
    "delta_time = (time() - start_time) / 60.0\n",
    "\n",
    "y_pred = qmodel.forward(X_test, fhe=\"simulate\")\n",
    "accuracy = top_k_accuracy_score(y_true=y_test, y_score=y_pred, k=1, labels=numpy.arange(10))\n",
    "\n",
    "print(\n",
    "    f\"With p_error = {largest_p_error:.5f}, \"\n",
    "    f\"the inference time per example becomes {delta_time / len(y_fhe_test):.2f}s and \"\n",
    "    f\"accuracy = {accuracy:.2%}\"\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "execution": {
   "timeout": 10800
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
